⚡ 30 秒速记
- 核心判断:理解原理要建立输入、状态变化、输出和失败边界,而不是只记 API 与结论
- 原理主线:围绕 「Vue 异步更新 DOM 原理」、「总结」、「核心机制」 建立输入、状态变化与输出之间的因果关系
- 文章范围:解析了Vue中数据变更到视图异步更新的完整流程,介绍了Data、Dep、Watcher等核心对象的作用,阐释了为什么Vue更新DOM是异步的,以及如何通过$nextTick获取最新的DOM状态,帮助读者深入理解Vue异步渲染机制。
- 边界与代价:文章中的实现通常有版本和场景前提,迁移到当前项目时必须先核对运行环境与依赖
- 工程落地:面试回答按核心机制、执行链路、边界反例和工程验证展开,最后说明取舍
Vue 更新数据后不会立即操作 DOM,而是把相关 Watcher 去重后放进队列,在下一个 tick 统一刷新。 队列会按 Watcher 的 id 排序,使父组件优先更新,并处理刷新期间新增的任务。nextTick 会优先借助 Promise 等异步机制执行回调,所以在 $nextTick 中通常能读到更新后的 DOM。这里描述的是 Vue 2 的调度链路,Vue 3 的实现角色已经换成 Proxy、effect 和新的渲染器。
这篇文章不要按 API 清单来背。先用上面的 Mind Map 建立全局结构,再通过交互 DEMO 观察正常路径和边界路径如何改变状态;阅读正文时重点核对每一步的输入、负责执行的参与者、产生的中间状态以及最终可观察结果。遇到版本敏感结论,要把“历史实现”“当前行为”和“工程兼容策略”分开说明;遇到性能或架构取舍,则用实际指标、失败现象和验证手段支撑判断。
版本校准: 本文出现 Object.defineProperty、Dep、Watcher 和双端 Diff 时,主要描述 Vue 2 实现;Vue 3 使用 Proxy、effect 与新的渲染器路径。Vue 2 已于 2023-12-31 结束维护,新项目应以 Vue 3 为基线,旧项目参考 Vue 2 EOL 官方说明 制定迁移与安全策略。
本文主要分析 Vue 从 Data 更新,到通知 Watcher 异步更新视图的流程,也就是下图中的橙色部分。

我们先来回顾一下图中的几个对象:
- Data 对象:Vue 中的 data 方法中返回的对象。
- Dep 对象:每一个 Data 属性都会创建一个 Dep,用来搜集所有使用到这个 Data 的 Watcher 对象。
- Watcher 对象:主要用于渲染 DOM。
接下来,我们就开始分析这个流程。
# Vue 异步更新 DOM 原理
很多同学都知道,Vue 中的数据更新是异步的,意味着我们在修改完 Data 之后,并不能立刻获取修改后的 DOM 元素。
<template>
<div>
<span id="text">{{ message }}</span>
<button @click="changeData">
changeData
</button>
</div>
</template>
<script>
export default {
data() {
return {
message: "hello",
};
},
methods: {
changeData() {
this.message = "hello world";
const textContent = document.getElementById("text").textContent;
// 直接获取,不是最新的
console.log(textContent === "hello world"); // false
// $nextTick 回调中,是最新的
this.$nextTick(() => {
const textContent = document.getElementById("text").textContent;
console.warn(textContent === "hello world"); // true
});
},
},
};
</script>